/**
 * This file is released under the GNU General Public License.
 * Refer to the COPYING file distributed with this package.
 *
 * Copyright (c) 2008-2009 WURFL-Pro srl
 */
package net.sourceforge.wurfl.core;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.sourceforge.wurfl.core.resource.DeviceNotInModelException;
import net.sourceforge.wurfl.core.resource.ModelDevice;
import net.sourceforge.wurfl.core.resource.WURFLModel;

import org.apache.commons.lang.text.StrBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * CapabilityLoader implementation.
 * 
 * <p>
 * Loads all capabilities for specified Device by navigate his hierarchy.
 * </p>
 * 
 * @author WURFL-PRO SRL, Rome, Italy
 * @version $Id: DefaultCapabilitiesLoader.java 1045 2009-03-09 15:52:53Z filippo.deluca $
 */
public class DefaultCapabilitiesLoader implements CapabilitiesLoader {

	/** Instance of WURFLModel to load capabilities from */
	private WURFLModel model;

	/** The root ModelDevice of this Device, modelDevice.id = this.id */
	private ModelDevice modelDevice;

	/** Logger */
	private static final Log log = LogFactory.getLog(DefaultCapabilitiesLoader.class);

	/**
	 * Constructor by model and root device.
	 * 
	 * @param modelDevice
	 *            The root ModelDevice
	 * @param model
	 *            The model containing root device to load capabilities from.
	 */
	public DefaultCapabilitiesLoader(ModelDevice root, WURFLModel model) {

		this.model = model;
		this.modelDevice = root;
	}

	/**
	 * Load the capabilities from <code>model</code> iterating over the
	 * <code>root</code> device hierarchy.
	 * 
	 * <p>
	 * <strong>Hierarchy is defined as a ordered list of ModelDevice from
	 * "generic" to root.<br/>
	 * example:<br/>
	 * <code>generic->...->root</code></strong>
	 * </p>
	 * 
	 * <p>
	 * If The root ModelDevice is not contained in <code>model</code> this
	 * method return an empty Map. This happened if this instance is build
	 * passing it a unmanaged ModelDevice to constructor.
	 * </p>
	 */
	public Map loadCapabilities() {
		Map capabilities = new HashMap(model.getAllCapabilities().size());

		try {
			List hierarchy = model.getDeviceHierarchy(modelDevice);

			/*
			 * WARNING the hierarchy is defined by a ordered list defined as:
			 * <code>generic -> ... -> root</code>.
			 */
			for (Iterator iterator = hierarchy.iterator(); iterator.hasNext();) {
				ModelDevice device = (ModelDevice) iterator.next();
				capabilities.putAll(device.getCapabilities());
			}
		} catch (DeviceNotInModelException e) {
			/*
			 * If the model does not contain the root it return a empty Map.
			 * Maybe the root is unmanaged ModelDevice.
			 */
			if (log.isErrorEnabled()) {
				StrBuilder logBuilder = new StrBuilder();
				logBuilder.append("Device: ").append(modelDevice.getID())
						.append(" is not in model. ").append(
								"Capabilities will not loaded.");

				log.error(logBuilder.toString());
			}
		}

		return capabilities;
	}

}
